/*
 * Copyright 2018- The Pixie Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

syntax = "proto3";

package px.carnotpb;

option go_package = "carnotpb";

import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "src/api/proto/uuidpb/uuid.proto";
import "src/carnot/queryresultspb/query_results.proto";
import "src/table_store/schemapb/schema.proto";
import "src/common/base/statuspb/status.proto";

message TransferResultChunkRequest {
  // This field represents the address that the row batch should be sent to.
  string address = 1;
  // The ID of the remote query ID on the address that should receive this
  // RowBatch.
  uuidpb.UUID query_id = 2 [ (gogoproto.customname) = "QueryID" ];
  // Previously used for grpc_source_id and table_name before they were grouped under
  // the RowBatchResult message.
  reserved 3;
  reserved 4;
  // QueryResultContents is used to both initiate a connection between a GRPCSink and its remote
  // destination at the beginning of the stream, also to send any result RowBatches between the sink
  // and its destination. It contains metadata so that the sink->destination connection can be
  // tracked and monitored, and the overall query context cancelled if a particular
  // sink->destination stream has been closed earlier than expected.
  message SinkResult {
    oneof result_contents {
      // The row batch data.
      px.table_store.schemapb.RowBatchData row_batch = 1;
    }
    reserved 4;  // DEPRECATED: used to be initiate_result_stream. Replaced with InitiateConnection.
    oneof destination {
      // When the TransferResultChunkRequest is being sent to another Carnot instance,
      // 'grpc_source_id' identifies the source node within the query that should receive this
      // RowBatch.
      uint64 grpc_source_id = 2 [ (gogoproto.customname) = "GRPCSourceID" ];
      // If this result chunk is being sent to a non-Carnot instance such as the querybroker,
      // this field denotes the name of the table that it belongs to.
      string table_name = 3;
    }
  }
  // Execution and timing info for a given query. These are sent once per agent for a batch query
  // and periodically per agent for a streaming query.
  message QueryExecutionAndTimingInfo {
    // Previously used for query timing info, which is part of QueryExecutionStats here.
    reserved 1;
    // Execution info across the entire query, sent by the top-level agent in the plan.
    px.carnot.queryresultspb.QueryExecutionStats execution_stats = 2;
    // Agent-specific execution stats, sent by every agent in the plan.
    repeated px.carnot.queryresultspb.AgentExecutionStats agent_execution_stats = 3;
  }
  message InitiateConnection {}

  oneof result {
    // `query_result` covers query result data sent from a GRPC sink (including the request
    // to initiate the connection between the GRPC sink and its destination).
    SinkResult query_result = 5;
    // Execution information about the query.
    // This result will be sent periodically until the end of the query, so it also functions
    // as a heartbeat for persistent streaming queries.
    QueryExecutionAndTimingInfo execution_and_timing_info = 6;
    // Whenever an error occurs, it will be stored in this field.
    px.statuspb.Status execution_error = 7;
    // The message sent during query initialization. Signals that the query has started.
    InitiateConnection initiate_conn = 8;
  }
}

message TransferResultChunkResponse {
  // This field indicates whether or not the transfer of the stream of ResultChunks
  // completed successfully.
  bool success = 1;
  // This field has any error message, if applicable.
  string message = 2;
}

service ResultSinkService {
  // Transfer a result chunk (which could be eithr data or metadata) for a given query, to another
  // Carnot instance or to an external sink.
  rpc TransferResultChunk(stream TransferResultChunkRequest) returns (TransferResultChunkResponse);
}
